package com.unistec.fileserver.client;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.alibaba.fastjson.JSONObject;
import com.unistec.fileserver.client.entity.Resource;
import com.unistec.fileserver.client.feign.IFileServerFeign;
import com.unistec.framework.exception.NotifyException;
import com.unistec.framework.utils.FileUtils;
import com.unistec.framework.utils.JsonUtils;
import com.unistec.framework.utils.Objects;
import com.unistec.framework.utils.ReturnResult;
import com.unistec.framework.utils.SpringUtils;

import feign.Response;

/**
 * 文件上传API
 * 
 * @description
 * @author 胡晓光
 * @date 2021-9-28
 * @time 11:03:42
 *
 */
public class FileServerAPI {
	static Logger logger = LoggerFactory.getLogger(FileServerAPI.class);

	/**
	 * 删除文件
	 * 
	 * @description
	 * @author 胡晓光
	 * @date 2021-9-28
	 * @time 10:54:41
	 * 
	 * @param foreignId
	 */
	public static void deleteFile(String foreignId) {
		IFileServerFeign uploadFeign = SpringUtils.getBean(IFileServerFeign.class);
		uploadFeign.deleteFile(foreignId);
	}

	/**
	 * 上传永久文件
	 * 
	 * @description
	 * @author 胡晓光
	 * @date 2021-9-28
	 * @time 11:00:19
	 * 
	 * @param file             需要上传的文件
	 * @param replacedFileName 需要替换的文件名，可为空
	 * @param asyncUpload      是否异步上传，可为空
	 * @param uploadId         上传id，可为空
	 * @param siteId           子站id，可为空
	 * @return
	 */
	public static Resource uploadFile(InputStream in, String replacedFileName, Boolean asyncUpload, String path, Boolean isTempFile, String uploadId) {
		if (Objects.isNull(replacedFileName)) {
			throw new NotifyException("必须指定文件名称[replacedFileName]");
		}

		IFileServerFeign uploadFeign = SpringUtils.getBean(IFileServerFeign.class);

		FileItem fileItem = null;
		try {
			fileItem = createFileItem(in, replacedFileName);
		} catch (Exception e) {
			throw new NotifyException("文件不存在");
		}

		// CommonsMultipartFile是feign对multipartFile的封装，但是要FileItem类对象
		MultipartFile mfile = new CommonsMultipartFile(fileItem);

		JSONObject result = uploadFeign.uploadFile(mfile, asyncUpload, path, replacedFileName, isTempFile, uploadId);
		if (Objects.isNull(result) || !result.getBooleanValue("success") || Objects.isNull(result.getJSONObject("data"))) {
			throw new NotifyException("文件上传失败");
		}
		return JsonUtils.JSONObject2Bean(result.getJSONObject("data"), Resource.class);
	}

	/**
	 * 上传永久文件
	 * 
	 * @description
	 * @author 胡晓光
	 * @date 2021-9-28
	 * @time 11:00:19
	 * 
	 * @param file             需要上传的文件
	 * @param replacedFileName 需要替换的文件名，可为空
	 * @param asyncUpload      是否异步上传，可为空
	 * @param uploadId         上传id，可为空
	 * @param siteId           子站id，可为空
	 * @return
	 */
	public static Resource uploadFile(MultipartFile file, String replacedFileName, Boolean asyncUpload, String path, Boolean isTempFile, String uploadId) {
		IFileServerFeign uploadFeign = SpringUtils.getBean(IFileServerFeign.class);

		// CommonsMultipartFile是feign对multipartFile的封装，但是要FileItem类对象
		JSONObject result = uploadFeign.uploadFile(file, asyncUpload, path, replacedFileName, isTempFile, uploadId);
		if (Objects.isNull(result) || !result.getBooleanValue("success") || Objects.isNull(result.getJSONObject("data"))) {
			throw new NotifyException("文件上传失败");
		}
		return JsonUtils.JSONObject2Bean(result.getJSONObject("data"), Resource.class);
	}

	/**
	 * 上传永久文件
	 * 
	 * @description
	 * @author 胡晓光
	 * @date 2021-9-28
	 * @time 11:00:19
	 * 
	 * @param file             需要上传的文件
	 * @param replacedFileName 需要替换的文件名，可为空
	 * @param asyncUpload      是否异步上传，可为空
	 * @param uploadId         上传id，可为空
	 * @param siteId           子站id，可为空
	 * @return
	 */
	public static Resource uploadFile(File file, String replacedFileName, Boolean asyncUpload, String path, Boolean isTempFile, String uploadId) {
		IFileServerFeign uploadFeign = SpringUtils.getBean(IFileServerFeign.class);

		FileItem fileItem = null;
		try {
			fileItem = createFileItem(new FileInputStream(file), Objects.isNull(replacedFileName) ? file.getName() : replacedFileName);
		} catch (Exception e) {
			throw new NotifyException("文件不存在");
		}

		// CommonsMultipartFile是feign对multipartFile的封装，但是要FileItem类对象
		MultipartFile mfile = new CommonsMultipartFile(fileItem);

		JSONObject result = uploadFeign.uploadFile(mfile, asyncUpload, path, replacedFileName, isTempFile, uploadId);
		if (Objects.isNull(result) || !result.getBooleanValue("success") || Objects.isNull(result.getJSONObject("data"))) {
			throw new NotifyException("文件上传失败");
		}
		return JsonUtils.JSONObject2Bean(result.getJSONObject("data"), Resource.class);
	}

	/**
	 * 通过唯一值获取资源
	 * 
	 * @description
	 * @author 胡晓光
	 * @date 2021-9-28
	 * @time 11:02:53
	 * 
	 * @param unique 唯一值
	 * @return
	 */
	public static Resource getFileByUnique(String unique) {
		if (Objects.isNull(unique)) {
			return null;
		}

		IFileServerFeign uploadFeign = SpringUtils.getBean(IFileServerFeign.class);
		ReturnResult<Resource> returnResult = uploadFeign.getResourceInfoByUnique(unique);
		if (Objects.nonNull(returnResult) && returnResult.isSuccess() && Objects.nonNull(returnResult.getData())) {
			return returnResult.getData();
		}
		return null;
	}

	/**
	 * 通过唯一值获取资源
	 * 
	 * @description
	 * @author 胡晓光
	 * @date 2021-9-28
	 * @time 11:02:53
	 * 
	 * @param unique 唯一值
	 * @return
	 */
	public static File downloadFile(String unique) {
		if (Objects.isNull(unique)) {
			return null;
		}

		IFileServerFeign uploadFeign = SpringUtils.getBean(IFileServerFeign.class);

		String extention = FileUtils.getUriExtention(unique); 

		if (Objects.isNull(extention)) {
			// 首先取到资源
			Resource resource = null;
			ReturnResult<Resource> returnResult = uploadFeign.getResourceInfoByUnique(unique);
			if (Objects.isNull(returnResult) || !returnResult.isSuccess() || Objects.isNull(returnResult.getData())) {
				throw new NotifyException("文件不存在");
			}
			resource = returnResult.getData();
			extention = resource.getFilenameSuffix();
		}

		// 创建一个临时文件
		File tempFile = FileUtils.createTempFile(extention);

		// 调用下载接口
		Response response = uploadFeign.download(unique);
		Response.Body body = response.body();

		try (InputStream in = body.asInputStream()) {
			// 保存流到临时文件中
			FileUtils.saveInputStream(in, tempFile);
			return tempFile;
		} catch (Exception e) {
			logger.error("文件下载失败[" + tempFile.getPath() + "]", e);
			throw new NotifyException("文件下载失败");
		}
	}

	// FileItem类对象创建
	private static FileItem createFileItem(InputStream fis, String fileName) {
		FileItemFactory factory = new DiskFileItemFactory(10240 * 1024 * 5, null);
		String textFieldName = "file";

		FileItem item = factory.createItem(textFieldName, "multipart/form-data", true, fileName);
		int bytesRead = 0;

		byte[] buffer = new byte[8192];

		// 使用输出流输出输入流的字节
		try (OutputStream os = item.getOutputStream()) {
			while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
				os.write(buffer, 0, bytesRead);
			}
			os.close();
			fis.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
		}
		return item;
	}
}
